By Marco C. Mason
Suppose that you manage a large network where multiple machines
need to have a local copy of some set of files, and you're frequently
updating these same files. You start ftp and transfer the files
like this (what you type is in italics):
$ ftp widget1.cobb.zd.com
Connected to widget1.
220 widget1 FTP server (UNIX(r) System V Release 4.0) ready.
Name (Widget1:marco): anonymous
331 Guest login ok, send ident as password.
Password:
ftp> cd /pub/data
250 CWD command successful.
ftp> put daily.summary
200 PORT command successful.
150 ASCII data connection for
daily.summary (140.244.96.202,32817)
226 Transfer complete.
local: daily.summary remote: daily.summary
21468 bytes sent in 11.32 seconds (1.9 Kbytes/s)
ftp>
Ugh! You've sent only one file, and you've barely gotten started. If you need to send a few files in different subdirectories to a dozen machines, you'll be baby-sitting ftp for quite a while. Wouldn't it be better if a command could do all the transfers for you?
In this article, we'll show you how to create macros to make large file transfer jobs simpler using ftp. We'll also show you how to make ftp automatically log you in when you specify the computer to which you want to connect.
The first thing we can do to make ftp simpler to use is to create macros for common tasks. You can create your own commands in ftp by building them out of other ftp commands. These new commands are called macros. You create your commands with the macdef command. To use the macdef command, all you need to do is type macdef and follow it with the name of your new macro. Then, type each command you want your new macro to perform. When you're finished, enter a blank line to tell ftp that your macro is complete.
Figure A shows an example macro, named transfer, that will copy
our daily summary files to a remote machine. Please note that
this macro assumes that we're already connected to the machine.
Figure A
macdef transfer
cd /pub/data
put daily.summary
put graphs/daily.orders
put graphs /daily.inquiries
put graphs /daily.cancels
cd /pub/spreadsheets
put daily.worksheet.wks
<blank line>
Now that we have our macro, transferring a set of files from our
machine to a remote machine is simpler. Once we're connected,
all we have to do is tell ftp to execute the new macro. You do
so by entering $macroname at an ftp prompt, like this:
ftp> $transfer
Even though transferring all the files to a single remote computer
is simple, we still must connect to each machine that we need
to update and then execute our macro command. Fortunately, there's
a better way. You can write a macro that accepts arguments. In
other words, you can write a macro so that when you execute it
like this
ftp> $send_files widget1
widget2 arthur
your macro has the ability to read the arguments widget1, widget2, and arthur. To do so, when you write your macro, use the character sequence $1 to refer to the first argument, $2 to refer to the second, and so on. Therefore, we could write the send_files macro to send our files to the machines widget1, widget2, and arthur, as shown in Figure B.
Please note that each argument is separated by spaces, unless
you use quotes. If you use quotes, you may embed spaces in your
arguments. Thus $transfer "arg 1" "arg 2"
has only two arguments.
Figure B
macdef send_files
open $1
$transfer
close
open $2
$transfer
close
open $3
$transfer
close
<blank line>
Figure C
macdef send_files
open $i
$transfer
close
<blank line>
This method is a lot better. Now you can start ftp, issue the send_files macro with the list of machines you want to send the files to, and walk away. No more baby-sitting the computer.
However, this macro could still be improved. First, it's repetitious--whenever you do repetitive tasks on a computer, there's usually a better way. Second, what happens if you want to transfer the daily summaries to more or fewer than three machines?
Both of these problems can be solved by another special character sequence: $i. When you use $i in a macro definition, you're telling ftp to execute the macro once for each argument. The first time ftp executes the macro, $i refers to the first argument. The second time it executes the macro, $i refers to the second argument, and so on, until there are no arguments left. Thus, we can rewrite our send_files macro as shown in Figure C. Using our improved send_files macro, we can transfer our daily summaries to as many machines as we want, simply and easily.
Of course, not all is wine and roses. When you're using macros with ftp, you're limited to having only 16 defined at one time. Another limitation is that all your macros combined must have less than 4,096 characters.
In addition, since the $ symbol is used in macro definitions, you can't blithely use it whenever you want one in your macros. In order to put a $ in your macro definitions, you must precede the $ with a \. To put a \ in your macro definitions, you must use \\.
While macros are a very nice feature, why use them if you have to redefine them each time you start the ftp program? Fortunately, the designers had similar thoughts: When you start ftp, it looks in your $HOME directory for a file named .netrc. If it finds this file, it will automatically scan this file for macro definitions and load them into memory. By the time you get to the first prompt, all the macro definitions in the .netrc file are ready to use.
You can put a macro in your .netrc file by entering it just as you would at the ftp prompt. Don't forget to place a blank line after the last line in the macro to end the macro!
Do you find yourself executing the same set of commands each time you run ftp? If so, you'll like one of the other benefits of using the .netrc file. It turns out that when ftp loads all the macros in the .netrc file, if it finds one named init, ftp executes it before giving you control.
For example, when you transmit a large file, do you enjoy staring at the screen waiting for the transfer to complete? Neither do we. When we start a file transfer, we open a new terminal window and work on a different project.
Just so we can tell how things are progressing, we always execute the hash command so that ftp will print hash marks (#) as it transfers the file. This way, we can easily look up from our job to see if ftp is still banging away. Similarly, we execute the bell command so that ftp beeps us when the transfer is complete. This allows us to take a break from our other project and start the next file transfer operation.
Rather than execute the bell and hash commands each time we start ftp, we created the init macro, shown in Figure D, in our .netrc file to execute them for us.
Figure D
macdef init
bell
hash
<blank line>
When you examine Figures B and C, you might think we made an error. After all, the open command doesn't automatically log you in, does it? By itself, it doesn't. But if you put the machine definition information into your .netrc file, it can. This is a great feature even if you're not using macros, as it can help you log in to machines without having to type in your user name and password each time.
When you start ftp with a host name on the command line like this
ftp widget1.cobb.zd.com
or if you simply try to open a connection from an ftp prompt,
like this
ftp> open widget1.cobb.zd.com
ftp scans its list of machine definitions and, if it finds the specified machine in its list, it will provide whatever information it has. If you specify all the information required, then ftp will automatically log you in without prompting you for the user name and password.
You can create a machine definition by putting the following text
in your .netrc file:
machine machine_name
login user_name
password password
All you need to do is replace the italicized text with the required information. You can put the machine, login, and password clauses on a single line if you prefer.
Combining all the concepts we've talked about, we created a .netrc
file, shown in Figure E, that contains our macros and machine
names so we can perform all our daily summary updates just by
starting ftp and typing
$transfer widget1 widget2
arthur
Figure E
machine widget1 login anonymous password marco@widget1
machine widget2 login anonymous
password marco@widget1
machine arthur
login marco
password splemliferous
macdef init
bell
hash
macdef transfer
cd /pub/data
put daily.summary
put graphs/daily.orders
put graphs /daily.inquiries
put graphs /daily.cancels
cd /pub/spreadsheets
put daily.worksheet.wks
macdef send_files
open $i
$transfer
close
Occasionally, you may need to log in to a computer with a different account than the one described in your .netrc file. In this case, you need a way to tell ftp to ignore the machine definition information in your .netrc file but to otherwise run normally.
You can do this by starting ftp with the -n option. This tells
ftp to read only the macros from the .netrc file and to
ignore the machine definitions. When you use the -n option, you'll
have to log in to each machine manually. To start ftp using this
switch, just type
ftp -n hostname
All the features provided by the .netrc command are great time-savers. However, there's one security problem that you need to be aware of. If you use the automatic login feature with a real account (i.e., not an anonymous login), then anyone who can read your .netrc file can find out your user name and password on that machine.
You can plug this security hole by telling Solaris not to let
anyone read the file but you. You can do so by using the command
chmod go-r .netrc
This command tells Solaris to remove the read permission from
other accounts inside and outside of your group. Now no one may
read your .netrc file but you, the root, and the superuser accounts.
As you can see, ftp has some very powerful features that let you
customize its operation. If you take full advantage of the macro
facilities and the machine-definition features, you can simplify
your daily chores considerably.
Marco C. Mason is a freelance computer consultant and author
based in Louisville, Kentucky. He's worked on cattle feeding systems,
automated destructive equipment testing, and the largest computer-controlled
sound system in the world.
[Return to Index for Inside Solaris - April 1996 Issue]
Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.